#!/usr/bin/python
#-----------------------------------------------------------------------------
# Copyright 2009, Graham Jones, based on pyroute gui.py by Oliver White
# Copyright 2007, Oliver White
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#-----------------------------------------------------------------------------
import pygtk
pygtk.require('2.0')
import gobject
import gtk
import sys
import cairo
import urllib
import os
from math import sqrt
from time import *
from gtk import gdk

# This adds the pyroute subdirectory of the current working directory
# to the module search path - it is to save having everything in one directory.
#sys.path.append('./pyroute')
# Our modules:
from tilenames import *
from projection import Projection
#from guiOverlay import *
from dataStore import *
from base import pyrouteModule
from tiles import tileHandler
from events import pyrouteEvents
#from sketch import sketching
#from tracklog import tracklog
from meta import moduleInfo
from tracklog_overlay import tracklog_overlay


def update(mapWidget):
  mapWidget.update();
  return(True)

class MapWidget(gtk.Widget, pyrouteModule):
  __gsignals__ = { \
    'realize': 'override',
    'expose-event' : 'override',
    'size-allocate': 'override',
    'size-request': 'override'
    }
  def __init__(self):
    gtk.Widget.__init__(self)
    self.draw_gc = None
    
    self.modules = {'poi':{}}
    pyrouteModule.__init__(self, self.modules)

    self.debug = True
    
    self.loadModules()
    self.blankData()
    self.loadData()
    self.timer = gobject.timeout_add(100, update, self)
    print "MapWidget init finished"
    
  def loadModules(self):
#    self.modules['overlay'] = guiOverlay(self.modules)
    self.modules['tiles'] = tileHandler(self.modules)
    self.modules['data'] = DataStore(self.modules)
    self.modules['events'] = pyrouteEvents(self.modules)
    self.modules['projection'] = Projection()
    self.modules['tracklog_overlay'] = tracklog_overlay(self.modules)
    
#  def addModule(self,modname,module):
#    if self.debug: print "addModule(): Adding module %s." % modname
#    self.modules[modname] = module(self.modules)
#    if self.debug: print "addModule(): Module %s added." % modname
    

  def setPosition(self,lat,lon,zoom):
    """Set the map position and zoom level"""
    if self.debug: print "mapwidget.setPosition()."
    self.m['projection'].recentre(lat,lon,zoom)
    self.forceRedraw()

  def blankData(self):
    self.set('ownpos', {'valid':False})
    self.set('mode','cycle')
    self.set('centred',False)
    self.set('logging',True)
    self.m['projection'].recentre(51.3,-0.1, 9)
  
  def loadData(self):
    print "loadData()"
    
  def beforeDie(self):
    print "Handling last few checks before we close"
  
  def update(self):
    if(self.get("needRedraw")):
      self.forceRedraw()
      
  def mousedown(self,x,y):
    if(self.get('sketch',0)):
      self.m['sketch'].startStroke(x,y)
    
  def click(self, x, y):
    """Handle clicking on the screen"""
    print "Clicked %d,%d"%(x,y)
    # Give the overlay a chance to handle all clicks first
    #if(self.m['overlay'].handleClick(x,y)):
    #  pass
    # If the overlay is fullscreen and it didn't respond, the click does
    # not fall-through to the map
    #elif(self.m['overlay'].fullscreen()):
    #  return
    #elif(self.get('sketch',0)):
    #  return
    # Map was clicked-on: store the lat/lon and go into the "clicked" menu
    #else:
    lat, lon = self.m['projection'].xy2ll(x,y)
      #self.set('clicked', (lat,lon))
    self.modules['projection'].recentre(lat, lon)
      #self.set('menu','click')
    self.forceRedraw()
      
  def forceRedraw(self):
    """Make the window trigger a draw event.  
    TODO: consider replacing this if porting pyroute to another platform"""
    self.set("needRedraw", False)
    try:
      self.window.invalidate_rect((0,0,self.rect.width,self.rect.height),False)
    except AttributeError:
      pass
    
  def move(self,dx,dy):
    """Handle dragging the map"""
    # TODO: what happens when you drag inside menus?
    if(self.get('menu')):
      return
    if(self.get('centred') and self.get('ownpos')['valid']):
      return
    self.modules['projection'].nudge(dx,dy)
    self.forceRedraw()
  
  def zoom(self,inc):
    """Adjust zoom level by specified increment"""
    self.modules['projection'].setZoom(inc,True)
    self.forceRedraw()

  def handleDrag(self,x,y,dx,dy,startX,startY):
    self.move(dx,dy)
    

  def draw(self, cr):
    start = clock()
    proj = self.modules['projection']
    
    # Don't draw the map if a menu/overlay is fullscreen
    #if(not self.modules['overlay'].fullscreen()):
      # Map as image
    self.modules['tiles'].draw(cr)
#      self.m['sketch'].draw(cr,proj)
    self.m['tracklog_overlay'].draw(cr,proj)
      
    pos = self.get('ownpos')
    if(pos['valid']):
      # Us
      x,y = proj.ll2xy(pos['lat'], pos['lon'])
      cr.set_source_rgb(0.0, 0.0, 0.0)
      cr.arc(x,y,14, 0,2*3.1415)
      cr.fill()
      cr.set_source_rgb(1.0, 0.0, 0.0)
      cr.arc(x,y,10, 0,2*3.1415)
      cr.fill()
      

    # Overlay (menus etc)
    #self.modules['overlay'].draw(cr, self.rect)
    
    #print "Map took %1.2f ms" % (1000 * (clock() - start))
    
  def do_realize(self):
    self.set_flags(self.flags() | gtk.REALIZED)
    self.window = gdk.Window( \
      self.get_parent_window(),
      width = self.allocation.width,
      height = self.allocation.height,
      window_type = gdk.WINDOW_CHILD,
      wclass = gdk.INPUT_OUTPUT,
      event_mask = self.get_events() | gdk.EXPOSURE_MASK)
    self.window.set_user_data(self)
    self.style.attach(self.window)
    self.style.set_background(self.window, gtk.STATE_NORMAL)
    self.window.move_resize(*self.allocation)

  def do_size_request(self, allocation):
    pass

  def do_size_allocate(self, allocation):
    self.allocation = allocation
    if self.flags() & gtk.REALIZED:
      self.window.move_resize(*allocation)

  def _expose_cairo(self, event, cr):
    self.rect = self.allocation
    self.modules['projection'].setView( \
      self.rect.x, 
      self.rect.y, 
      self.rect.width, 
      self.rect.height)
    self.draw(cr)

  def do_expose_event(self, event):
    self.chain(event)
    cr = self.window.cairo_create()
    return self._expose_cairo(event, cr)
